/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 146 $
 * @author  $Author: bacr $
 * @date    $Date: 2013-10-02 17:56:25 +0200 (mer., 02 oct. 2013) $
 *
 ***************************************************************************/

#ifndef __PTP2_TASK_QUEUE_H__
#define __PTP2_TASK_QUEUE_H__

typedef enum   ptp2_task_queue_priority_t   ptp2_task_queue_priority_t;
typedef struct ptp2_task_queue_entry_t      ptp2_task_queue_entry_t;
typedef struct ptp2_task_queue_t            ptp2_task_queue_t;

#include "object.h"

#include "hcpp/ptp2_task.h"

enum ptp2_task_queue_priority_t {
    PTP2_TASK_QUEUE_NONE = 0,
    PTP2_TASK_QUEUE_TIMER,
    PTP2_TASK_QUEUE_HIGH,
    PTP2_TASK_QUEUE_MEDIUM,
    PTP2_TASK_QUEUE_LOW,
    PTP2_TASK_QUEUE_RECURRENT
};

/** internal task queue entry structure*/
struct ptp2_task_queue_entry_t {
    struct ptp2_task_queue_entry_t *prev;
    struct ptp2_task_queue_entry_t *next;
    ptp2_task_t                    *task;
    bool                            recurrent;
    uint32_t                        timeout;
    uint32_t                        msec;           /**< time to fire */
};

/** task queue structure */
struct ptp2_task_queue_t {
    object_t                        obj;
    uint32_t                        msec;           /**< current time */
    ptp2_task_queue_entry_t         prio_timer;     /**< timer queue */
    ptp2_task_queue_entry_t         prio_high;      /**< high-priority queue */
    ptp2_task_queue_entry_t         prio_medium;    /**< medium-priority queue */
    ptp2_task_queue_entry_t         prio_low;       /**< low-priority queue */
    ptp2_task_queue_entry_t         prio_recurrent; /**< recurrent-priority queue */
};

ptp2_task_queue_t *PTP2_TASK_QUEUE(void);

bool          ptp2_task_queue_init(ptp2_task_queue_t *this);
void          ptp2_task_queue_tick(ptp2_task_queue_t *this, uint32_t msec);
bool          ptp2_task_queue_add(ptp2_task_queue_t *this, ptp2_task_queue_priority_t prio, ptp2_task_t *task);
bool          ptp2_task_queue_add_timer(ptp2_task_queue_t *this, ptp2_task_t *task, bool recurrent, uint32_t timeout);
ptp2_task_t  *ptp2_task_queue_next(ptp2_task_queue_t *this);

#endif

